package com.southsmart.springboot.smartdoc.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import com.southsmart.springboot.smartdoc.constant.LevelEnum;
import com.southsmart.springboot.smartdoc.dto.AdministrativeDivisionDTO;
import com.southsmart.springboot.smartdoc.dto.AdministrativeDivisionTreeDTO;
import com.southsmart.springboot.smartdoc.dto.AdministrativeLevelDTO;
import com.southsmart.springboot.smartdoc.entity.AdministrativeDivisionEntity;
import com.southsmart.springboot.smartdoc.mapper.AdministrativeDivisionMapper;
import com.southsmart.springboot.smartdoc.service.IAdministrativeDivisionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AdministrativeDivisionServiceImpl :  服务接口实现
 *
 * @author : CaoLongMin
 * @since 2021-04-20
 * @version 1.0
 */
@Service
public class AdministrativeDivisionServiceImpl implements IAdministrativeDivisionService {
    @Autowired
    private AdministrativeDivisionMapper administrativeDivisionMapper;

    /**
     * 动态组成查询条件
     *
     * @param administrativeDivisionDTO 传输对象
     */
    private LambdaQueryWrapper<AdministrativeDivisionEntity> buildCondition(AdministrativeDivisionDTO administrativeDivisionDTO) {
        LambdaQueryWrapper<AdministrativeDivisionEntity> wrapper = new LambdaQueryWrapper<>();
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getId())) {
            wrapper.like(AdministrativeDivisionEntity::getId,administrativeDivisionDTO.getId());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getCode())) {
            wrapper.like(AdministrativeDivisionEntity::getCode,administrativeDivisionDTO.getCode());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getParentCode())) {
            wrapper.like(AdministrativeDivisionEntity::getParentCode,administrativeDivisionDTO.getParentCode());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getName())) {
            wrapper.like(AdministrativeDivisionEntity::getName,administrativeDivisionDTO.getName());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getMergerName())) {
            wrapper.like(AdministrativeDivisionEntity::getMergerName,administrativeDivisionDTO.getMergerName());
        }
            //其他类型用等于
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getLevelType())) {
           wrapper.eq(AdministrativeDivisionEntity::getLevelType,administrativeDivisionDTO.getLevelType());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getCityCode())) {
            wrapper.like(AdministrativeDivisionEntity::getCityCode,administrativeDivisionDTO.getCityCode());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getZipCode())) {
            wrapper.like(AdministrativeDivisionEntity::getZipCode,administrativeDivisionDTO.getZipCode());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getPinYin())) {
            wrapper.like(AdministrativeDivisionEntity::getPinYin,administrativeDivisionDTO.getPinYin());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getJianPin())) {
            wrapper.like(AdministrativeDivisionEntity::getJianPin,administrativeDivisionDTO.getJianPin());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getFirstChar())) {
            wrapper.like(AdministrativeDivisionEntity::getFirstChar,administrativeDivisionDTO.getFirstChar());
        }
            //其他类型用等于
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getLng())) {
           wrapper.eq(AdministrativeDivisionEntity::getLng,administrativeDivisionDTO.getLng());
        }
            //其他类型用等于
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getLat())) {
           wrapper.eq(AdministrativeDivisionEntity::getLat,administrativeDivisionDTO.getLat());
        }
            //字符串用like
        if (!StringUtils.isEmpty(administrativeDivisionDTO.getRemarks())) {
            wrapper.like(AdministrativeDivisionEntity::getRemarks,administrativeDivisionDTO.getRemarks());
        }
        return wrapper;
    }

    @Override
    public PageInfo<AdministrativeDivisionDTO> pageList(int pageNo, int pageSize, AdministrativeDivisionDTO administrativeDivisionDTO) {
        PageHelper.startPage(pageNo, pageSize);
        List<AdministrativeDivisionDTO> dtos = new ArrayList<>();
        List<AdministrativeDivisionEntity> entities = administrativeDivisionMapper.selectList(buildCondition(administrativeDivisionDTO));

        PageInfo<AdministrativeDivisionEntity> pageInfo = new PageInfo<>(entities);
        for(AdministrativeDivisionEntity entity : entities){
            AdministrativeDivisionDTO dto  = new AdministrativeDivisionDTO();
            BeanUtils.copyProperties(entity,dto);
            dtos.add(dto);
        }
        //保存dto分页信息
        PageInfo<AdministrativeDivisionDTO> page = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo,page);
        page.setList(dtos);
        return page;
    }

    @Override
    public AdministrativeDivisionDTO selectById(String id) {
    AdministrativeDivisionDTO administrativeDivisionDTO=new AdministrativeDivisionDTO();
        BeanUtils.copyProperties(administrativeDivisionMapper.selectById(id),administrativeDivisionDTO);
        return administrativeDivisionDTO;
    }

    @Override
    public int deleteByIds(List<String> list) {
        return administrativeDivisionMapper.deleteBatchIds(list);
    }

    @Override
    public Boolean insert(AdministrativeDivisionDTO administrativeDivisionDTO) {
        dataValidation(administrativeDivisionDTO,true);
        AdministrativeDivisionEntity administrativeDivisionEntity=new AdministrativeDivisionEntity();
        BeanUtil.copyProperties(administrativeDivisionDTO,administrativeDivisionEntity);
        administrativeDivisionMapper.insert(administrativeDivisionEntity);
        return true;
    }

    @Override
    public Boolean update(AdministrativeDivisionDTO administrativeDivisionDTO) {
        dataValidation(administrativeDivisionDTO,false);
        AdministrativeDivisionEntity administrativeDivisionEntity=new AdministrativeDivisionEntity();
        BeanUtil.copyProperties(administrativeDivisionDTO,administrativeDivisionEntity);
        administrativeDivisionMapper.updateById(administrativeDivisionEntity);
        return true;
    }


    public void dataValidation(AdministrativeDivisionDTO administrativeDivisionDTO,Boolean isAdd){
        if(BeanUtil.isEmpty(administrativeDivisionDTO)){
            throw new ApiException("数据为空");
        }
        if(StringUtils.isEmpty(administrativeDivisionDTO.getCode())){
            throw new ApiException("行政区划代码不能为空");
        }
        if(StringUtils.isEmpty(administrativeDivisionDTO.getParentCode())){
            throw new ApiException("父级行政区划代码不能为空");
        }
        if(StringUtils.isEmpty(administrativeDivisionDTO.getName())){
            throw new ApiException("行政区名称不能为空");
        }
        if(StringUtils.isEmpty(administrativeDivisionDTO.getLevelType())){
            throw new ApiException("行政区划级别不能为空");
        }
        Boolean isType=false;
        for(LevelEnum levelEnum:LevelEnum.values()){
            if(levelEnum.getCode().equals(administrativeDivisionDTO.getLevelType())){
                isType=true;
                break;
            }
        }
        if(!isType){
            throw new ApiException("行政区级别错误：levelType="+administrativeDivisionDTO.getLevelType()+"应为：0-国家；1-省；2-市；3-区县");
        }
        //查询行政区代码是否已存在
        LambdaQueryWrapper<AdministrativeDivisionEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AdministrativeDivisionEntity::getCode,administrativeDivisionDTO.getCode());
        if(!isAdd){
            lambdaQueryWrapper.ne(AdministrativeDivisionEntity::getId,administrativeDivisionDTO.getId());
        }
        List<AdministrativeDivisionEntity> list=administrativeDivisionMapper.selectList(lambdaQueryWrapper);
        if(BeanUtil.isNotEmpty(list)&&list.size()>0){
            throw new ApiException("行政区划代码：" + administrativeDivisionDTO.getCode() + "已存在，不能添加");
        }
    }
    @Override
    public List<AdministrativeLevelDTO> getLevelList() {
        List<AdministrativeLevelDTO> resultList=new ArrayList<>();
        for(LevelEnum levelEnum:LevelEnum.values()){
            AdministrativeLevelDTO administrativeLevelDTO=new AdministrativeLevelDTO();
            administrativeLevelDTO.setLevelCode(levelEnum.getCode());
            administrativeLevelDTO.setLevelName(levelEnum.getName());
            resultList.add(administrativeLevelDTO);
        }
        return resultList;
    }

    @Override
    public Boolean validAdminCode(String code) {
        LambdaQueryWrapper<AdministrativeDivisionEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AdministrativeDivisionEntity::getCode,code);
        List<AdministrativeDivisionEntity> resultList=administrativeDivisionMapper.selectList(lambdaQueryWrapper);
        if(BeanUtil.isNotEmpty(resultList)&&resultList.size()>0){
            return true;
        }else{
            return false;
        }

    }

    @Override
    public List<AdministrativeDivisionTreeDTO> getAdministrativeTreeByCode(String code) {
        LambdaQueryWrapper<AdministrativeDivisionEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(AdministrativeDivisionEntity::getCode);
        List<AdministrativeDivisionEntity> entityList = administrativeDivisionMapper.selectList(lambdaQueryWrapper);
        List<AdministrativeDivisionTreeDTO> resultList=new ArrayList<>();
        if(StringUtils.isEmpty(code)){
            resultList = entityList.stream()
                    .filter(entity -> entity.getParentCode().equals("0"))
                    .map(entity -> covertMenuNode(entity, entityList)).collect(Collectors.toList());
        }else{
            resultList = entityList.stream()
                    .filter(entity -> entity.getCode().equals(code))
                    .map(entity -> covertMenuNode(entity, entityList)).collect(Collectors.toList());
        }
        return resultList;
    }

    @Override
    public List<AdministrativeDivisionTreeDTO> getAdministrativeTreeByLevel(Integer levelType) {
        LambdaQueryWrapper<AdministrativeDivisionEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(AdministrativeDivisionEntity::getCode);
        List<AdministrativeDivisionEntity> entityList = administrativeDivisionMapper.selectList(lambdaQueryWrapper);
        List<AdministrativeDivisionTreeDTO> resultList=new ArrayList<>();
        if(StringUtils.isEmpty(levelType)){
            resultList = entityList.stream()
                    .filter(entity -> entity.getLevelType().equals(0))
                    .map(entity -> covertMenuNode(entity, entityList)).collect(Collectors.toList());
        }else{
            resultList = entityList.stream()
                    .filter(entity -> entity.getLevelType().equals(levelType))
                    .map(entity -> covertMenuNode(entity, entityList)).collect(Collectors.toList());
        }
        return resultList;
    }

    /**
     * 递归获取下级目录
     */
    private AdministrativeDivisionTreeDTO covertMenuNode(AdministrativeDivisionEntity entity, List<AdministrativeDivisionEntity> entityList) {
        AdministrativeDivisionTreeDTO node = new AdministrativeDivisionTreeDTO();
        BeanUtils.copyProperties(entity, node);
        List<AdministrativeDivisionDTO> children = entityList.stream()
                .filter(subMenu -> subMenu.getParentCode().equals(entity.getId()))
                .map(subMenu -> covertMenuNode(subMenu, entityList)).collect(Collectors.toList());
        node.setChildNode(children);
        return node;
    }
}
